package org.jeecg.modules.system.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.api.client.json.Json;
import com.xkcoding.justauth.AuthRequestFactory;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.config.AuthDefaultSource;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.PasswordUtil;
import org.jeecg.common.util.RedisUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.base.service.BaseCommonService;
import org.jeecg.modules.system.entity.SysThirdAccount;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.model.ThirdLoginModel;
import org.jeecg.modules.system.service.ISysDepartService;
import org.jeecg.modules.system.service.ISysThirdAccountService;
import org.jeecg.modules.system.service.ISysUserService;
import org.jeecg.modules.tt_question_collect.util.TransUntil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.swing.text.html.parser.Entity;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * @Author scott
 * @since 2018-12-17
 */
@Controller
@RequestMapping("/sys/thirdLogin")
@Slf4j
public class ThirdLoginController {

    @Value("${justauth.type.WECHAT_ENTERPRISE_WEB.client-id}")
    private String clientid;
    @Value("${justauth.type.WECHAT_ENTERPRISE_WEB.client-secret}")
    private String clientsecret;

    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private ISysThirdAccountService sysThirdAccountService;

    @Autowired
    private BaseCommonService baseCommonService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private AuthRequestFactory factory;

    @Autowired
    private ISysDepartService sysDepartService;





    @AutoLog(value = "同步更新企业微信组织架构")
    @ApiOperation(value = "同步更新企业微信组织架构", notes = "同步更新企业微信组织架构")
    @GetMapping(value = "/tbupdatewechat")
    public Result<?> Wechat_Tb_ud() {
        String source ="https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid="+clientid+"&corpsecret="+clientsecret;
        System.out.println(clientid+clientsecret);
        JSONObject access_tokken = TransUntil.sendPost(source,null);
        System.out.println(access_tokken);
        System.out.println( access_tokken.get("access_token").toString());
        String tokken = access_tokken.get("access_token").toString();

        String fetch_chilid = null;
        //获取部门列表
        String bmhttpurl = "https://qyapi.weixin.qq.com/cgi-bin/department/list?access_token="+tokken;


        JSONObject bmjson = TransUntil.sendPost(bmhttpurl,null);
        System.out.println(bmjson.get("department"));



        List<Map<String,Object>>  objectlist  = (List<Map<String, Object>>) bmjson.get("department");

        sysDepartService.savdepartmodel(objectlist);

//        for (int i = 0; i <objectlist.size() ; i++) {
//          //  System.out.println("部门名称--------"+objectlist.get(i).get("name"));
//
//            fetch_chilid = objectlist.get(i).get("id").toString();
//
//            //根据部门id获取部门成员
//            String bmusresurl = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token="+tokken+"&department_id="+fetch_chilid+"&fetch_child=0";
//             JSONObject bmuserlists = TransUntil.sendPost(bmusresurl,null);
//            System.out.println("部门成员----"+objectlist.get(i).get("name")+":------------"+bmuserlists);
//
//
//        }
        return Result.OK();
    }



    @RequestMapping("/render/{source}")
    public void render(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        log.info("第三方登录进入render：" + source);
        AuthRequest authRequest = factory.get(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info("第三方登录认证地址：" + authorizeUrl);
        response.sendRedirect(authorizeUrl);
    }

    /**
     * 获取网页授权登录地址
     * 当前仅支持企业微信，未研究是否支持其它三方平台
     *
     * @param source
     * @param response
     * @throws IOException
     */
    @ResponseBody
    @GetMapping("/render/phone/{source}")
    public Result<String> renderPhone(@PathVariable("source") String source, HttpServletResponse response) throws IOException {
        Result<String> result = new Result<>();
        log.info("第三方登录进入render：" + source);
        if (!AuthDefaultSource.WECHAT_ENTERPRISE_WEB.toString().equals(source.toUpperCase())) {
            result.setSuccess(false);
            result.setMessage("非法请求，当前不支持该平台登录！");
            return result;
        }
        AuthRequest authRequest = factory.get(source);
        String authorizeUrl = authRequest.authorize(AuthStateUtils.createState());
        log.info("第三方登录认证授权地址：" + authorizeUrl);
        result.setSuccess(true);
        result.setResult(authorizeUrl);
        return result;
    }

    /**
     * 网页授权登录，暂时仅支持企业微信
     * @param source
     * @param callback
     * @return
     * @throws IOException
     */
    @ResponseBody
    @GetMapping("/phone/{source}/callback")
    public Result<JSONObject> phoneLoginThird(@PathVariable("source") String source, AuthCallback callback) throws IOException {
        Result<JSONObject> result = new Result<JSONObject>();
        JSONObject jsonObject = new JSONObject();
        log.info("第三方登录进入callback：" + source + " params：" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = factory.get(source);
        AuthResponse response = authRequest.login(callback);
//        JSONObject jsonObject1 = new JSONObject();
//        jsonObject1.put("uuid", "huhjfd1635431");
//        AuthResponse response = new AuthResponse(2000, "成功", jsonObject1);
        log.info(JSONObject.toJSONString(response));
        if (response.getCode() == 2000) {
            if ("wechat_enterprise_web".equals(source)) {
                source = "wechat_enterprise";
            }
            JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(response.getData()));
            String username = data.getString("username");
            String avatar = data.getString("avatar");
            String uuid = data.getString("uuid");
            //构造第三方登录信息存储对象
            ThirdLoginModel tlm = new ThirdLoginModel(source, uuid, username, avatar);
            //判断有没有这个人
            LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<SysThirdAccount>();
            query.eq(SysThirdAccount::getThirdUserUuid, uuid);
            query.eq(SysThirdAccount::getThirdType, source);
            List<SysThirdAccount> thridList = sysThirdAccountService.list(query);
            SysThirdAccount user = null;
            if (thridList == null || thridList.size() == 0) {
                //否则直接创建新账号
                user = saveThirdUser(tlm);
            }
            else {
                //已存在 只设置用户名 不设置头像
                user = thridList.get(0);
            }
            // 生成token
            if (oConvertUtils.isNotEmpty(user.getSysUserId())) {
                String sysUserId = user.getSysUserId();
                SysUser sysUser = sysUserService.getById(sysUserId);
                String token = saveToken(sysUser);
                jsonObject.put("token", token);
                result.setSuccess(true);
                result.setResult(jsonObject);
            }
            else {
                jsonObject.put("token", "绑定手机号," + "" + uuid);
                result.setSuccess(true);
                result.setResult(jsonObject);
            }
        }
        else {
            result.setSuccess(false);
            result.setMessage("第三方登录异常,请联系管理员。" + JSONObject.toJSONString(response));
        }
        System.out.println(JSON.toJSONString(result));
        return result;
    }

    @RequestMapping("/{source}/callback")
    public String loginThird(@PathVariable("source") String source, AuthCallback callback, ModelMap modelMap) {
        log.info("第三方登录进入callback：" + source + " params：" + JSONObject.toJSONString(callback));
        AuthRequest authRequest = factory.get(source);
        AuthResponse response = authRequest.login(callback);
        log.info(JSONObject.toJSONString(response));
        Result<JSONObject> result = new Result<JSONObject>();
        if (response.getCode() == 2000) {

            JSONObject data = JSONObject.parseObject(JSONObject.toJSONString(response.getData()));
            String username = data.getString("username");
            String avatar = data.getString("avatar");
            String uuid = data.getString("uuid");
            //构造第三方登录信息存储对象
            ThirdLoginModel tlm = new ThirdLoginModel(source, uuid, username, avatar);
            //判断有没有这个人
            //update-begin-author:wangshuai date:20201118 for:修改成查询第三方账户表
            LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<SysThirdAccount>();
            query.eq(SysThirdAccount::getThirdUserUuid, uuid);
            query.eq(SysThirdAccount::getThirdType, source);
            List<SysThirdAccount> thridList = sysThirdAccountService.list(query);
            SysThirdAccount user = null;
            if (thridList == null || thridList.size() == 0) {
                //否则直接创建新账号
                user = saveThirdUser(tlm);
            }
            else {
                //已存在 只设置用户名 不设置头像
                user = thridList.get(0);
            }
            // 生成token
            //update-begin-author:wangshuai date:20201118 for:从第三方登录查询是否存在用户id，不存在绑定手机号
            if (oConvertUtils.isNotEmpty(user.getSysUserId())) {
                String sysUserId = user.getSysUserId();
                SysUser sysUser = sysUserService.getById(sysUserId);
                String token = saveToken(sysUser);
                modelMap.addAttribute("token", token);
            }
            else {
                modelMap.addAttribute("token", "绑定手机号," + "" + uuid);
            }
            //update-end-author:wangshuai date:20201118 for:从第三方登录查询是否存在用户id，不存在绑定手机号
            //update-begin--Author:wangshuai  Date:20200729 for：接口在签名校验失败时返回失败的标识码 issues#1441--------------------
        }
        else {
            modelMap.addAttribute("token", "登录失败");
        }
        //update-end--Author:wangshuai  Date:20200729 for：接口在签名校验失败时返回失败的标识码 issues#1441--------------------
        result.setSuccess(false);
        result.setMessage("第三方登录异常,请联系管理员");
        return "thirdLogin";
    }

    /**
     * 创建新账号
     *
     * @param model
     * @return
     */
    @PostMapping("/user/create")
    @ResponseBody
    public Result<String> thirdUserCreate(@RequestBody ThirdLoginModel model) {
        log.info("第三方登录创建新账号：");
        Result<String> res = new Result<>();
        Object operateCode = redisUtil.get(CommonConstant.THIRD_LOGIN_CODE);
        if (operateCode == null || !operateCode.toString().equals(model.getOperateCode())) {
            res.setSuccess(false);
            res.setMessage("校验失败");
            return res;
        }
        //创建新账号
        //update-begin-author:wangshuai date:20201118 for:修改成从第三方登录查出来的user_id，在查询用户表尽行token
        SysThirdAccount user = saveThirdUser(model);
        if (oConvertUtils.isNotEmpty(user.getSysUserId())) {
            String sysUserId = user.getSysUserId();
            SysUser sysUser = sysUserService.getById(sysUserId);
            // 生成token
            String token = saveToken(sysUser);
            //update-end-author:wangshuai date:20201118 for:修改成从第三方登录查出来的user_id，在查询用户表尽行token
            res.setResult(token);
            res.setSuccess(true);
        }
        return res;
    }

    /**
     * 绑定账号 需要设置密码 需要走一遍校验
     *
     * @param json
     * @return
     */
    @PostMapping("/user/checkPassword")
    @ResponseBody
    public Result<String> checkPassword(@RequestBody JSONObject json) {
        Result<String> result = new Result<>();
        Object operateCode = redisUtil.get(CommonConstant.THIRD_LOGIN_CODE);
        if (operateCode == null || !operateCode.toString().equals(json.getString("operateCode"))) {
            result.setSuccess(false);
            result.setMessage("校验失败");
            return result;
        }
        String username = json.getString("uuid");
        SysUser user = this.sysUserService.getUserByName(username);
        if (user == null) {
            result.setMessage("用户未找到");
            result.setSuccess(false);
            return result;
        }
        String password = json.getString("password");
        String salt = user.getSalt();
        String passwordEncode = PasswordUtil.encrypt(user.getUsername(), password, salt);
        if (!passwordEncode.equals(user.getPassword())) {
            result.setMessage("密码不正确");
            result.setSuccess(false);
            return result;
        }

        sysUserService.updateById(user);
        result.setSuccess(true);
        // 生成token
        String token = saveToken(user);
        result.setResult(token);
        return result;
    }

    /**
     * 创建新用户
     *
     * @param tlm 第三方登录信息
     */
    private SysThirdAccount saveThirdUser(ThirdLoginModel tlm) {
        SysThirdAccount user = new SysThirdAccount();
        user.setDelFlag(CommonConstant.DEL_FLAG_0);
        user.setStatus(1);
        user.setThirdType(tlm.getSource());
        user.setAvatar(tlm.getAvatar());
        user.setRealname(tlm.getUsername());
        user.setThirdUserUuid(tlm.getUuid());
        sysThirdAccountService.save(user);
        return user;
    }

    private String saveToken(SysUser user) {
        // 生成token
        String token = JwtUtil.sign(user.getUsername(), user.getPassword());
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        // 设置超时时间
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
        return token;
    }

    @SuppressWarnings("unchecked")
    @RequestMapping(value = "/getLoginUser/{token}/{thirdType}", method = RequestMethod.GET)
    @ResponseBody
    public Result<JSONObject> getThirdLoginUser(@PathVariable("token") String token, @PathVariable("thirdType") String thirdType) throws Exception {
        Result<JSONObject> result = new Result<JSONObject>();
        String username = JwtUtil.getUsername(token);

        //1. 校验用户是否有效
        SysUser sysUser = sysUserService.getUserByName(username);
        result = sysUserService.checkUserIsEffective(sysUser);
        if (!result.isSuccess()) {
            return result;
        }
        //update-begin-author:wangshuai date:20201118 for:如果真实姓名和头像不存在就取第三方登录的
        LambdaQueryWrapper<SysThirdAccount> query = new LambdaQueryWrapper<>();
        query.eq(SysThirdAccount::getSysUserId, sysUser.getId());
        query.eq(SysThirdAccount::getThirdType, thirdType);
        SysThirdAccount account = sysThirdAccountService.getOne(query);
        if (oConvertUtils.isEmpty(sysUser.getRealname())) {
            sysUser.setRealname(account.getRealname());
        }
        if (oConvertUtils.isEmpty(sysUser.getAvatar())) {
            sysUser.setAvatar(account.getAvatar());
        }
        //update-end-author:wangshuai date:20201118 for:如果真实姓名和头像不存在就取第三方登录的
        JSONObject obj = new JSONObject();
        //用户登录信息
        obj.put("userInfo", sysUser);
        //token 信息
        obj.put("token", token);
        result.setResult(obj);
        result.setSuccess(true);
        result.setCode(200);
        baseCommonService.addLog("用户名: " + username + ",登录成功[第三方用户]！", CommonConstant.LOG_TYPE_1, null);
        return result;
    }

    /**
     * 第三方绑定手机号返回token
     *
     * @param jsonObject
     * @return
     */
    @ApiOperation("手机号登录接口")
    @PostMapping("/bindingThirdPhone")
    @ResponseBody
    public Result<String> bindingThirdPhone(@RequestBody JSONObject jsonObject) {
        Result<String> result = new Result<String>();
        String phone = jsonObject.getString("mobile");
        String thirdUserUuid = jsonObject.getString("thirdUserUuid");
        String thirdDept = jsonObject.getString("thirdDept");
        //校验用户有效性
        SysUser sysUser = sysUserService.getUserByPhone(phone);
        if (sysUser != null) {
            sysThirdAccountService.updateThirdUserId(sysUser, thirdUserUuid);
        }
        else {
            // 不存在手机号，创建用户
            String smscode = jsonObject.getString("captcha");
            Object code = redisUtil.get(phone);
            if (!smscode.equals(code)) {
                result.setMessage("手机验证码错误");
                result.setSuccess(false);
                return result;
            }
            //创建用户
            sysUser = sysThirdAccountService.createUser(phone, thirdUserUuid, thirdDept);
        }
        String token = saveToken(sysUser);
        result.setSuccess(true);
        result.setResult(token);
        return result;
    }
}
